#ifndef DRIVER_H
#define DRIVER_H

#include <QString>
#include <QList>

#include "vehicle.h"
#include "streetmap.h"

using namespace GeometryUtilities;

class DriverType
{
public:
  DriverType();
  QString name;
  qreal followDistance;
  qreal visibilityDistance;
  qreal reactionTime;
  qreal preferredTurnSpeed;
  qreal preferredAcceleration;
  qreal jerk;
  qreal defaultSpeed;
};

class Driver
{
public:
  enum GoalType
  {
    GOAL_WAYPOINT,
    GOAL_CUSTOM_WAYPOINT,
    GOAL_OBSTACLE,
    GOAL_LANE
  };

  Driver(const QString &name);
  Driver(const QString &name, Vehicle *vehicle);
  void tick();
  //void followPath();
  bool driveToGoal(const Point &goal, const GoalType goalType=GOAL_WAYPOINT);
  bool checkLane(Point &laneGoal);
  bool checkCollisions(Point &collision);
  bool checkTrafficControls(Point &controlPoint);
  void setName(const QString &value);
  QString name();
  void getIn(Vehicle *vehicle);
  void getIn(const QString &vehicleName);
  void getOut();
  Point destination();
  void addWaypoint(const Point &p);
  void addWaypoint(const QString &intersectionName);
  void calculatePath();
  void adjustWaypoint();

  qreal mPreferredTurnSpeed;
  qreal mPreferredAcceleration;
  qreal mJerk;
  Point mCurrentGoal;
  Point mCurrentWaypoint;
  qreal mReactionTime;          // in seconds
  Vehicle *mVehicle;
  Driver *mYieldingTo;
  qreal mPrevSteerVal;
  qreal mDesiredDirection;
  qreal mDesiredSpeed;          // in MPH
  qreal mDistToGoal;            // in meters
  qreal mTimeToGoal;            // in seconds
  qreal mSpeedDelta;
  qreal mPrevSpeedDelta;
  qreal mHeadingDelta;
  qreal mDefaultSpeed;          // in MPH
  const StreetMap::Road *mCurrentRoad;
  const StreetMap::Intersection *mLastIntersection;
  bool mWaypointAdjusted;
  StreetMap::Road::Lane mCurrentLane;
  unsigned int mCurrentLaneIndex;
  bool mStoppedAtLight;


private:
  void drive(float urgency);//changes throttle brake, steer values only, not intelligence
  QString mName;
  Point mDestination;
  bool mHasPath;
  bool mIsCalculatingPath; // perhaps if we thread this
  bool mReachedDestination;
  bool mStopping;
  qreal mLastTurnSpeed;
  bool mUpcomingTurn;
  bool mCrashed;

  qreal P, I, D, speedDiff;

  class MapPoint
  {
  public:
    MapPoint(const StreetMap::Intersection *intrSection, const Point &location);
    const StreetMap::Intersection *intersection;
    Point loc;
  };

  QList<MapPoint> mPath; //includes destination, but not start location
};

#endif // DRIVER_H
